package com.dh.spring.client.netty;

import com.dh.spring.util.LocalTime;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * @Auther: YSFY
 * @Date: 2019/12/6 21:28
 * @Pacage_name: com.dh.spring.server.bio
 * @Project_Name: CustomNettyClient
 * @Description: 基于Netty的客户端
 *
 */

public class CustomNettyClient {
    private final static Logger logger = LoggerFactory.getLogger(CustomNettyClient.class);
    private final static Integer MAX_RETRY = 5;

    public void start() {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap
                .group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .remoteAddress(new InetSocketAddress("192.168.1.3", 10090))
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        System.out.println(nioSocketChannel);
                    }
                });

            this.connect(bootstrap, MAX_RETRY);
        } finally {
            eventLoopGroup.shutdownGracefully();
        }
    }

    private ChannelFuture connect(Bootstrap bootstrap, Integer retry) {
        try {
            ChannelFuture channelFuture = bootstrap.connect().addListener(new GenericFutureListener<Future<? super Void>>() {
                @Override
                public void operationComplete(Future<? super Void> future) throws Exception {
                    if(future.isSuccess()) {
                        logger.info("[" + LocalTime.formatDate(LocalDateTime.now()) + "] ----------- netty client连接服务端成功 -----------");
                    } else if(0 == retry) {
                        logger.info("[" + LocalTime.formatDate(LocalDateTime.now()) + "] ----------- 重连已达最大上限连接次数，将禁止连接，客户端连接未成功 -----------");
                    } else { //TODO 尝试重新连接
                        int next = (MAX_RETRY - retry) + 1; //TODO 第几次重连
                        int delay = 1 << next; //TODO 本次重连间隔

                        logger.info("[" + LocalTime.formatDate(LocalDateTime.now()) + "] ----------- 开始尝试第 " + next + "次重连...... -----------");
                        bootstrap.config().group().schedule(() -> connect(bootstrap, delay - 1), delay, TimeUnit.SECONDS);
                    }
                }
            }).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
            logger.info("[" + LocalTime.formatDate(LocalDateTime.now()) + "] ----------- netty client连接出现InterruptedException：" + e.getMessage() + " -----------");
        }

        return null;
    }
    public static void main(String[] args) {
        new CustomNettyClient().start();

    }
}
